#include "myHashSet.h"
#include "malloc.h"


//初始化HashSet--填充空列表
void initMyHashSet(MyHashSet *mhset) {
    int i;
    for(i=0; i<mhset->Capacity; i++)
        mhset->dataList[i] = createMySearchList(mhset->equal);
}

//创建HashSet  
MyHashSet *createMyHashSet(int (*hashCode)(LNTYPE data, int Capacity), int (*equal)(LNTYPE data1,LNTYPE data2)) {
    MyHashSet *mhset = malloc(sizeof(MyHashSet));
    mhset->size = 0;
    mhset->Capacity = DEFAULT_INITIAL_CAPACITY;
    mhset->loadFactor = DEFAULT_LOAD_FACTOR;
    mhset->hashCode = hashCode;
    mhset->equal = equal;
    mhset->dataList = malloc(sizeof(void*)*DEFAULT_INITIAL_CAPACITY);
    initMyHashSet(mhset);
    return mhset;
}

//使用全部参数创建HashSet  
MyHashSet *createMyHashSetForAll(int Capacity,float loadFactor,int (*hashCode)(LNTYPE data, int Capacity),int (*equal)(LNTYPE data1,LNTYPE data2)) {
    MyHashSet *mhset = createMyHashSet(hashCode, equal);
    free(mhset->dataList);
    mhset->Capacity = Capacity;
    mhset->loadFactor = loadFactor;
    mhset->dataList = malloc(sizeof(void*)*Capacity);
    initMyHashSet(mhset);
    return mhset;
}


//释放HashSet  
void freeMyHashSet(MyHashSet * set) {
    int i;
    for(i=0; i<set->Capacity; i++)
        freeMyList(set->dataList[i]);
    free(set);
}

//释放HashSet,列表节点为堆指针一同释放
void freeMyHashSetP(MyHashSet * set) {
    int i;
    for(i=0; i<set->Capacity; i++)
        freeMyListP(set->dataList[i]);
    free(set);
}

//是否包含某个data  
int myHashSetContains(MyHashSet * const set, LNTYPE  const data) {
    int HashCode = (*set->hashCode)(data, set->Capacity);
    return myListFindDataIndex(set->dataList[HashCode], data) > -1;
}

//是否包含某个data,返回data地址,否则NULL
//This is only for Set2Map  
LNTYPE *myHashSetContains2(MyHashSet * const set, LNTYPE  const data) {
    int HashCode = (*set->hashCode)(data, set->Capacity);
    return myListFindDataAddr(set->dataList[HashCode], data);
}

//创建迭代器,可直接free  
MyHashSetIterator* createMyHashSetIterator(MyHashSet * const set) {
    MyHashSetIterator *mhIt = malloc(sizeof(MyHashSetIterator));
    mhIt->index = 0;
    mhIt->set = set;
    mhIt->count = 0;
    mhIt->current = set->dataList[0]->first;
    return mhIt;
}

//获取下一条数据  
LNTYPE myHashSetIteratorNext(MyHashSetIterator* iterator) {  
    (iterator->count)++;  
    while (!(iterator->current))  
    {  
        (iterator->index)++;  
        iterator->current = iterator->set->dataList[iterator->index]->first;  
    }  
    LNTYPE data = iterator->current->data;  
    iterator->current = iterator->current->next;  
    return data;  
} 

//迭代器是否有下一个  
int myHashSetIteratorHasNext(MyHashSetIterator* iterator) {  
    return iterator->count < iterator->set->size;  
}

//释放迭代器,直接free即可 
//void freeMyHashSetIterator(MyHashSetIterator* iterator);

//HashSet扩容
void rebuildMyHashSet(MyHashSet *set) {
    int nC = set->Capacity*2;
    MyList **ndL = malloc(sizeof(void*)*nC);
    int i;
    for(i=0; i<nC; i++) {
        ndL[i] = createMySearchList(set->equal);
    }
    MyHashSetIterator *it = createMyHashSetIterator(set);  
    while (it->count < it->set->size) {  
        LNTYPE data = myHashSetIteratorNext(it);  
        int hasCode = (*(set->hashCode))(data, nC);  
        myListInsertDataAtLast(ndL[hasCode], data);  
    }  
    free(it);  
    for (i=0; i<set->Capacity; i++)  
    {  
        freeMyList(set->dataList[i]);  
    }  
    free(set->dataList);  
    set->dataList = ndL;  
    set->Capacity = nC;
}


//增加一条数据,返回是否添加成功  
int myHashSetAddData(MyHashSet * const set, LNTYPE  const data) {
    int HashCode = (*set->hashCode)(data, set->Capacity);
    if(myListFindDataIndex(set->dataList[HashCode], data) > -1)
        return 0;
    myListInsertDataAtLast(set->dataList[HashCode], data);
    set->size++;
    if(set->size > set->Capacity*set->loadFactor)
        rebuildMyHashSet(set);
    return 1;
}

//增加一条数据
//This is only for Set2Map
void myHashSetAddData2(MyHashSet * const set, LNTYPE  const data) {
    int HashCode = (*set->hashCode)(data, set->Capacity);
    LNTYPE *fdp = myListFindDataAddr(set->dataList[HashCode], data);
    if(fdp) *fdp = data;
    else {
        myListInsertDataAtLast(set->dataList[HashCode], data);
        set->size++;
        if(set->size > set->Capacity*set->loadFactor)
            rebuildMyHashSet(set);
    }
}

//数据的容量  
int myHashSetGetSize(const MyHashSet * const set) {
    return set->size;
}

//删除一条数据，返回是否删除成功  
int myHashSetRemoveData(MyHashSet * const set, LNTYPE  const data) {
    int HashCode = (*set->hashCode)(data, set->Capacity);
    int res = myListRemoveDataObject(set->dataList[HashCode], data);
    if(res) set->size--;
    return res;
}

//遍历  
void myHashSetOutput(MyHashSet *set, void(*pt)(LNTYPE))  {  
    MyHashSetIterator * it=createMyHashSetIterator(set);  
    while (it->count < set->size) {  
        pt(myHashSetIteratorNext(it));  
    }  
    free(it);  
}

//***************Test**********
#include <stdio.h>
#include "myHashCode.h"
#include "myEqual.h"
#define S 10  
  
char* strs[S]=  {  
    "abc",  
    "qq",  
    "hello",  
    "abc",  
    "lmy",  
    "ab",  
    "qq",  
    "lqw",  
    "sww",  
    "lqw"  
};  

int main() {  
    //创建集合需要指定两个函数，hashCode函数和equal函数。  
    MyHashSet * set = createMyHashSet(myHashCodeString, myEqualString);  
  
    //插入数据 
    int i;
    for (i=0; i<S; i++)  
    {  
        myHashSetAddData(set, strs[i]);  
    }  
  
    //输出大小  
    printf("size=%d\n",myHashSetGetSize(set));  
  
    //测试删除  
    myHashSetRemoveData(set,"qq");  
    myHashSetRemoveData(set,"ab");  
    myHashSetRemoveData(set,"qwert");  
  
    //输出大小  
    printf("after remove size=%d\n",myHashSetGetSize(set));  
  
    //遍历  
    MyHashSetIterator * it = createMyHashSetIterator(set);  
    while(myHashSetIteratorHasNext(it))  
    {  
        char * pp= myHashSetIteratorNext(it);  
        puts(pp);  
    }  
    //释放遍历器  
    free(it);  
  
    //释放集合  
    freeMyHashSet(set);  
    return 0;  
} 

/*****************************/
